﻿using System;
using System.Collections.Generic;
using System.Text;
using JEng_Mark_1.Textures;
using JEng_Mark_1.Interfaces;
using JEng_Mark_1.GameComponents;
using JEng_Mark_1.Managers;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace JEng_Mark_1.GUI
{
    public class JGPanel : IJEngGuiObject
    {
        private bool _show = true;
        private bool _tiled = true;
        private Rectangle _rect;

        public bool BorderTiled { get { return _tiled; } set { _tiled = value; } }
        public Rectangle ObjectRect { get { return _rect; } set { _rect = value; } }
        public bool Show { get { return _show; } set { _show = value; } }

        private JTexture _tlPost,_trPost,_brPost,_blPost;
        private JTexture _tBorder,_rBorder,_bBorder,_lBorder;

        public JGPanel(JTexture TLPost, JTexture TRPost, JTexture BRPost, JTexture BLPost,
            JTexture TBorder, JTexture RBorder, JTexture BBorder, JTexture LBorder)
        {
            //remember post textures
            _tlPost = TLPost;
            _trPost = TRPost;
            _brPost = BRPost;
            _blPost = BLPost;
            //remember border textures
            _tBorder = TBorder;
            _rBorder = RBorder;
            _bBorder = BBorder;
            _lBorder = LBorder;
        }

        public void HandleInput(JInput input)
        {
            //Nothing to be clicked or interacted with on a panel
        }

        public void Draw()
        {
            if (Show)
            {
                //Temporary Texture2d objects
                Texture2D tlPost = _tlPost.BaseTexture as Texture2D;
                Texture2D trPost = _trPost.BaseTexture as Texture2D;
                Texture2D brPost = _brPost.BaseTexture as Texture2D;
                Texture2D blPost = _blPost.BaseTexture as Texture2D;
                Texture2D tBorder = _tBorder.BaseTexture as Texture2D;
                Texture2D rBorder = _rBorder.BaseTexture as Texture2D;
                Texture2D bBorder = _bBorder.BaseTexture as Texture2D;
                Texture2D lBorder = _lBorder.BaseTexture as Texture2D;

                SpriteBatch sb = JScreenManager.SpriteBatch;
                sb.Begin();
                //draw the borders
                if (!BorderTiled)
                {
                    sb.Draw(tBorder,
                        new Rectangle(ObjectRect.X + tlPost.Width, ObjectRect.Y, ObjectRect.Width - trPost.Width - tlPost.Width, tBorder.Height),
                        Color.White);
                    sb.Draw(rBorder,
                        new Rectangle(ObjectRect.Right - trPost.Width, ObjectRect.Y + trPost.Height, rBorder.Width, ObjectRect.Height - trPost.Height - brPost.Height),
                        Color.White);
                    sb.Draw(bBorder,
                        new Rectangle(ObjectRect.X + blPost.Width, ObjectRect.Bottom - bBorder.Height, ObjectRect.Width - brPost.Width - blPost.Width, bBorder.Height),
                        Color.White);
                    sb.Draw(lBorder,
                        new Rectangle(ObjectRect.X, ObjectRect.Y + tlPost.Height, lBorder.Width, ObjectRect.Height - trPost.Height - brPost.Height),
                        Color.White);
                }
                else
                {
                    TileBorder(tBorder,
                        new Rectangle(ObjectRect.X + tlPost.Width, ObjectRect.Y, ObjectRect.Width - trPost.Width - tlPost.Width, tBorder.Height),
                        sb, false);
                    TileBorder(rBorder,
                        new Rectangle(ObjectRect.Right - trPost.Width, ObjectRect.Y + trPost.Height, rBorder.Width, ObjectRect.Height - trPost.Height - brPost.Height),
                        sb, true);
                    TileBorder(bBorder,
                        new Rectangle(ObjectRect.X + blPost.Width, ObjectRect.Bottom - bBorder.Height, ObjectRect.Width - brPost.Width - blPost.Width, bBorder.Height),
                        sb, false);
                    TileBorder(lBorder,
                        new Rectangle(ObjectRect.X, ObjectRect.Y + tlPost.Height, lBorder.Width, ObjectRect.Height - trPost.Height - brPost.Height),
                        sb, true);

                }
                //draw the posts
                sb.Draw(tlPost,
                    new Rectangle(ObjectRect.X, ObjectRect.Y, tlPost.Width, tlPost.Height),
                    Color.White);
                sb.Draw(trPost,
                    new Rectangle(ObjectRect.Right - trPost.Width, ObjectRect.Y, trPost.Width, trPost.Height),
                    Color.White);
                sb.Draw(brPost,
                    new Rectangle(ObjectRect.Right - brPost.Width, ObjectRect.Bottom - brPost.Height, brPost.Width, brPost.Height),
                    Color.White);
                sb.Draw(blPost,
                    new Rectangle(ObjectRect.X, ObjectRect.Bottom - blPost.Height, blPost.Width, blPost.Height),
                    Color.White);
                
                sb.End();
            }
        }

        /// <summary>
        /// Draw a border to the screen and tile it to make a better fit / reduce stretching in the long direction
        /// </summary>
        /// <param name="tex">Texture to use, tiling info is pulled from image dimensions</param>
        /// <param name="upDir">True = Tile in the y direction, false = tile in the x direction</param>
        /// <param name="borderRect">Rectangle of full border piece</param>
        /// <param name="sb">SpriteBatch to draw with</param>
        private void TileBorder(Texture2D tex,Rectangle borderRect, SpriteBatch sb,bool upDir)
        {
            //compare total rectange to cover and image rectangle
            Rectangle imgRect = new Rectangle(0, 0, tex.Width, tex.Height);
            bool perfectFit = false;
            int yMod = borderRect.Height % imgRect.Height;
            int xMod = borderRect.Width % imgRect.Width;
            if (upDir)
            {
                //check for a perfect fit in the y direction
                if ((yMod) == 0)
                {
                    //perfect fit
                    perfectFit = true;
                }
            }
            else
            {
                //check for a perfect fit in the x direction
                if ((xMod) == 0)
                {
                    //perfect fit
                    perfectFit = true;
                }
            }

            // assume a perfect fit and adjust otherwise
            int yCount = borderRect.Height / imgRect.Height;
            int xCount = borderRect.Width / imgRect.Width;
            Rectangle drawRect = imgRect;
            if (!perfectFit)
            {
                int yShift = 0;
                int xShift = 0;
                if (upDir)
                {
                    if (yMod < (tex.Height / 2))
                    {
                        //up stretch each piece
                        yShift = (int)Math.Ceiling((double)yMod / yCount);
                    }
                    else
                    {
                        //add one and down stretch
                        yCount++;
                        yShift = (-1 * (yMod / yCount));
                    }
                }
                else
                {
                    if (xMod < (tex.Width / 2))
                    {
                        //up strectch each piece
                        xShift = (int)Math.Ceiling((double)xMod / xCount);
                    }
                    else
                    {
                        //add one and down stretch
                        xCount++;
                        xShift = (-1 * (xMod / xCount));
                    }
                }
                drawRect = new Rectangle(0, 0, imgRect.Width + xShift, imgRect.Height + yShift);
            }
            //if the panel is smaller than 1 tile
            if (yCount <= 0)
            {
                yCount = 1;
                drawRect = borderRect;
            }
            if (xCount <= 0)
            {
                xCount = 1;
                drawRect = borderRect;
            }
            //draw
            if (upDir)
            {
                //draw tiled along y dir
                for (int i = 0; i < yCount; i++)
                {
                    Rectangle finalRect = new Rectangle(borderRect.X,
                        borderRect.Y + (i * drawRect.Height),
                        drawRect.Width,
                        drawRect.Height + 1); //add 1 to height to account for rounding errors with ints
                    sb.Draw(tex, finalRect, Color.White);
                }
            }
            else
            {
                //draw tiled along x dir
                for (int i = 0; i < xCount; i++)
                {
                    Rectangle finalRect = new Rectangle(borderRect.X + (i * drawRect.Width),
                        borderRect.Y,
                        drawRect.Width + 1,
                        drawRect.Height); //add 1 to width to account for rounding errors with ints
                    sb.Draw(tex, finalRect, Color.White);
                }
            }
        }

        public event EventHandler<EventArgs> Clicked;
    }
}
